using AgentFrameworkDemo.Models;
using Microsoft.Extensions.Logging;
using System.Globalization;
using System.Text.RegularExpressions;
using ToolParameter = AgentFrameworkDemo.Models.ToolParameter;

namespace AgentFrameworkDemo.Services;

/// <summary>
/// 内置工具执行器
/// 实现数学计算、日期时间查询、文本处理等内置工具
/// </summary>
public class BuiltinToolExecutor : IToolExecutor
{
    private readonly ILogger<BuiltinToolExecutor> _logger;
    private readonly Dictionary<string, ToolDefinition> _builtinTools;

    public ToolType ToolType => ToolType.Builtin;

    public BuiltinToolExecutor(ILogger<BuiltinToolExecutor> logger)
    {
        _logger = logger;
        _builtinTools = InitializeBuiltinTools();
    }

    public async Task<List<ToolDefinition>> GetAvailableToolsAsync(string? agentId = null)
    {
        await Task.CompletedTask;
        return _builtinTools.Values.ToList();
    }

    public async Task<ToolExecutionResult> ExecuteToolAsync(ToolExecutionRequest request)
    {
        var startTime = DateTime.UtcNow;

        try
        {
            _logger.LogInformation("Executing builtin tool: {ToolId}", request.ToolId);

            if (!_builtinTools.TryGetValue(request.ToolId, out var toolDef))
            {
                return new ToolExecutionResult
                {
                    Success = false,
                    ErrorMessage = $"Tool not found: {request.ToolId}",
                    ToolId = request.ToolId,
                    ToolName = "Unknown",
                    ExecutionTime = DateTime.UtcNow - startTime,
                    ToolType = ToolType.Builtin
                };
            }

            // 验证参数
            var (isValid, errors) = await ValidateParametersAsync(request.ToolId, request.Parameters);
            if (!isValid)
            {
                return new ToolExecutionResult
                {
                    Success = false,
                    ErrorMessage = $"Parameter validation failed: {string.Join(", ", errors)}",
                    ToolId = request.ToolId,
                    ToolName = toolDef.Name,
                    ExecutionTime = DateTime.UtcNow - startTime,
                    ToolType = ToolType.Builtin
                };
            }

            // 执行具体工具
            object? result = request.ToolId switch
            {
                "math_calculate" => await ExecuteMathCalculation(request.Parameters),
                "datetime_now" => await ExecuteDateTimeNow(request.Parameters),
                "datetime_format" => await ExecuteDateTimeFormat(request.Parameters),
                "text_length" => await ExecuteTextLength(request.Parameters),
                "text_case" => await ExecuteTextCase(request.Parameters),
                "text_split" => await ExecuteTextSplit(request.Parameters),
                "system_info" => await ExecuteSystemInfo(request.Parameters),
                _ => throw new NotSupportedException($"Tool not supported: {request.ToolId}")
            };

            return new ToolExecutionResult
            {
                Success = true,
                Result = result,
                ToolId = request.ToolId,
                ToolName = toolDef.Name,
                ExecutionTime = DateTime.UtcNow - startTime,
                ToolType = ToolType.Builtin,
                Metadata = new Dictionary<string, object>
                {
                    ["agentId"] = request.AgentId,
                    ["sessionId"] = request.SessionId,
                    ["parameters"] = request.Parameters
                }
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to execute builtin tool: {ToolId}", request.ToolId);

            return new ToolExecutionResult
            {
                Success = false,
                ErrorMessage = ex.Message,
                ToolId = request.ToolId,
                ToolName = "Builtin Tool",
                ExecutionTime = DateTime.UtcNow - startTime,
                ToolType = ToolType.Builtin
            };
        }
    }

    public async Task<(bool isValid, List<string> errors)> ValidateParametersAsync(string toolId, Dictionary<string, object> parameters)
    {
        var errors = new List<string>();

        if (!_builtinTools.TryGetValue(toolId, out var toolDef))
        {
            errors.Add($"Tool not found: {toolId}");
            return (false, errors);
        }

        // 检查必需参数
        foreach (var param in toolDef.Parameters.Where(p => p.Value.Required))
        {
            if (!parameters.ContainsKey(param.Key) || parameters[param.Key] == null)
            {
                errors.Add($"Required parameter missing: {param.Key}");
            }
        }

        // 参数类型验证
        foreach (var param in parameters)
        {
            if (toolDef.Parameters.TryGetValue(param.Key, out var paramDef))
            {
                if (!ValidateParameterType(param.Value, paramDef.Type))
                {
                    errors.Add($"Invalid parameter type for {param.Key}: expected {paramDef.Type}, got {param.Value?.GetType().Name}");
                }
            }
        }

        await Task.CompletedTask;
        return (errors.Count == 0, errors);
    }

    public async Task<bool> IsToolAvailableAsync(string toolId)
    {
        await Task.CompletedTask;
        return _builtinTools.ContainsKey(toolId);
    }

    public async Task<ToolDefinition?> GetToolDefinitionAsync(string toolId)
    {
        await Task.CompletedTask;
        return _builtinTools.TryGetValue(toolId, out var toolDef) ? toolDef : null;
    }

    private Dictionary<string, ToolDefinition> InitializeBuiltinTools()
    {
        return new Dictionary<string, ToolDefinition>
        {
            ["math_calculate"] = new ToolDefinition
            {
                Id = "math_calculate",
                Name = "数学计算",
                Description = "执行基本数学运算（加减乘除、幂运算等）",
                Type = ToolType.Builtin,
                Parameters = new Dictionary<string, ToolParameter>
                {
                    ["expression"] = new ToolParameter
                    {
                        Name = "expression",
                        Type = "string",
                        Description = "数学表达式，如 '123 + 456', '2 ^ 10', 'sqrt(16)'",
                        Required = true
                    }
                },
                Tags = new List<string> { "math", "calculation", "builtin" }
            },

            ["datetime_now"] = new ToolDefinition
            {
                Id = "datetime_now",
                Name = "当前时间",
                Description = "获取当前日期时间",
                Type = ToolType.Builtin,
                Parameters = new Dictionary<string, ToolParameter>
                {
                    ["timezone"] = new ToolParameter
                    {
                        Name = "timezone",
                        Type = "string",
                        Description = "时区，如 'UTC', 'Asia/Shanghai'",
                        Required = false,
                        DefaultValue = "UTC"
                    },
                    ["format"] = new ToolParameter
                    {
                        Name = "format",
                        Type = "string",
                        Description = "日期时间格式，如 'yyyy-MM-dd HH:mm:ss'",
                        Required = false,
                        DefaultValue = "yyyy-MM-dd HH:mm:ss"
                    }
                },
                Tags = new List<string> { "datetime", "time", "builtin" }
            },

            ["datetime_format"] = new ToolDefinition
            {
                Id = "datetime_format",
                Name = "日期时间格式化",
                Description = "格式化指定的日期时间",
                Type = ToolType.Builtin,
                Parameters = new Dictionary<string, ToolParameter>
                {
                    ["datetime"] = new ToolParameter
                    {
                        Name = "datetime",
                        Type = "string",
                        Description = "要格式化的日期时间字符串",
                        Required = true
                    },
                    ["format"] = new ToolParameter
                    {
                        Name = "format",
                        Type = "string",
                        Description = "目标格式，如 'yyyy-MM-dd HH:mm:ss'",
                        Required = false,
                        DefaultValue = "yyyy-MM-dd HH:mm:ss"
                    }
                },
                Tags = new List<string> { "datetime", "format", "builtin" }
            },

            ["text_length"] = new ToolDefinition
            {
                Id = "text_length",
                Name = "文本长度",
                Description = "计算文本的字符数或单词数",
                Type = ToolType.Builtin,
                Parameters = new Dictionary<string, ToolParameter>
                {
                    ["text"] = new ToolParameter
                    {
                        Name = "text",
                        Type = "string",
                        Description = "要计算长度的文本",
                        Required = true
                    },
                    ["type"] = new ToolParameter
                    {
                        Name = "type",
                        Type = "string",
                        Description = "计算类型：'chars' 字符数，'words' 单词数，'lines' 行数",
                        Required = false,
                        DefaultValue = "chars",
                        EnumValues = new List<string> { "chars", "words", "lines" }
                    }
                },
                Tags = new List<string> { "text", "length", "builtin" }
            },

            ["text_case"] = new ToolDefinition
            {
                Id = "text_case",
                Name = "文本大小写转换",
                Description = "转换文本的大小写",
                Type = ToolType.Builtin,
                Parameters = new Dictionary<string, ToolParameter>
                {
                    ["text"] = new ToolParameter
                    {
                        Name = "text",
                        Type = "string",
                        Description = "要转换的文本",
                        Required = true
                    },
                    ["target_case"] = new ToolParameter
                    {
                        Name = "target_case",
                        Type = "string",
                        Description = "目标大小写：'upper', 'lower', 'title', 'sentence'",
                        Required = false,
                        DefaultValue = "upper",
                        EnumValues = new List<string> { "upper", "lower", "title", "sentence" }
                    }
                },
                Tags = new List<string> { "text", "case", "builtin" }
            },

            ["text_split"] = new ToolDefinition
            {
                Id = "text_split",
                Name = "文本分割",
                Description = "按指定分隔符分割文本",
                Type = ToolType.Builtin,
                Parameters = new Dictionary<string, ToolParameter>
                {
                    ["text"] = new ToolParameter
                    {
                        Name = "text",
                        Type = "string",
                        Description = "要分割的文本",
                        Required = true
                    },
                    ["separator"] = new ToolParameter
                    {
                        Name = "separator",
                        Type = "string",
                        Description = "分隔符，默认为逗号",
                        Required = false,
                        DefaultValue = ","
                    },
                    ["max_splits"] = new ToolParameter
                    {
                        Name = "max_splits",
                        Type = "number",
                        Description = "最大分割次数，-1表示无限制",
                        Required = false,
                        DefaultValue = -1
                    }
                },
                Tags = new List<string> { "text", "split", "builtin" }
            },

            ["system_info"] = new ToolDefinition
            {
                Id = "system_info",
                Name = "系统信息",
                Description = "获取系统环境信息",
                Type = ToolType.Builtin,
                Parameters = new Dictionary<string, ToolParameter>
                {
                    ["info_type"] = new ToolParameter
                    {
                        Name = "info_type",
                        Type = "string",
                        Description = "信息类型：'all', 'os', 'runtime', 'time'",
                        Required = false,
                        DefaultValue = "all",
                        EnumValues = new List<string> { "all", "os", "runtime", "time" }
                    }
                },
                Tags = new List<string> { "system", "info", "builtin" }
            }
        };
    }

    private async Task<object> ExecuteMathCalculation(Dictionary<string, object> parameters)
    {
        await Task.CompletedTask;

        var expression = parameters["expression"].ToString() ?? string.Empty;

        try
        {
            // 使用DataTable.Compute进行安全的数学计算
            var dataTable = new System.Data.DataTable();
            var result = dataTable.Compute(expression, string.Empty);

            return new
            {
                expression = expression,
                result = Convert.ToDouble(result),
                success = true
            };
        }
        catch (Exception ex)
        {
            return new
            {
                expression = expression,
                result = (object?)null,
                success = false,
                error = ex.Message
            };
        }
    }

    private async Task<object> ExecuteDateTimeNow(Dictionary<string, object> parameters)
    {
        await Task.CompletedTask;

        var timezone = parameters.GetValueOrDefault("timezone", "UTC").ToString();
        var format = parameters.GetValueOrDefault("format", "yyyy-MM-dd HH:mm:ss").ToString();

        try
        {
            DateTime now;
            if (!string.IsNullOrEmpty(timezone) && timezone != "UTC")
            {
                var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timezone);
                now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, timeZoneInfo);
            }
            else
            {
                now = DateTime.UtcNow;
            }

            return new
            {
                datetime = now.ToString(format),
                timezone = timezone ?? "UTC",
                format = format,
                timestamp = ((DateTimeOffset)now).ToUnixTimeSeconds()
            };
        }
        catch (Exception ex)
        {
            return new
            {
                datetime = DateTime.UtcNow.ToString(format),
                timezone = "UTC",
                format = format,
                error = ex.Message
            };
        }
    }

    private async Task<object> ExecuteDateTimeFormat(Dictionary<string, object> parameters)
    {
        await Task.CompletedTask;

        var datetimeStr = parameters["datetime"].ToString() ?? string.Empty;
        var format = parameters.GetValueOrDefault("format", "yyyy-MM-dd HH:mm:ss").ToString();

        try
        {
            if (DateTime.TryParse(datetimeStr, out var datetime))
            {
                return new
                {
                    original = datetimeStr,
                    formatted = datetime.ToString(format),
                    format = format,
                    success = true
                };
            }
            else
            {
                return new
                {
                    original = datetimeStr,
                    formatted = (object?)null,
                    format = format,
                    success = false,
                    error = "Invalid datetime string"
                };
            }
        }
        catch (Exception ex)
        {
            return new
            {
                original = datetimeStr,
                formatted = (object?)null,
                format = format,
                success = false,
                error = ex.Message
            };
        }
    }

    private async Task<object> ExecuteTextLength(Dictionary<string, object> parameters)
    {
        await Task.CompletedTask;

        var text = parameters["text"].ToString() ?? string.Empty;
        var type = parameters.GetValueOrDefault("type", "chars").ToString();

        var result = type switch
        {
            "words" => Regex.Matches(text, @"\b\w+\b").Count,
            "lines" => text.Split('\n').Length,
            _ => text.Length
        };

        return new
        {
            text = text,
            type = type,
            length = result,
            preview = text.Length > 50 ? text.Substring(0, 47) + "..." : text
        };
    }

    private async Task<object> ExecuteTextCase(Dictionary<string, object> parameters)
    {
        await Task.CompletedTask;

        var text = parameters["text"].ToString() ?? string.Empty;
        var targetCase = parameters.GetValueOrDefault("target_case", "upper").ToString();

        var result = targetCase switch
        {
            "lower" => text.ToLowerInvariant(),
            "title" => CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text.ToLowerInvariant()),
            "sentence" => char.ToUpper(text[0]) + text.Substring(1).ToLowerInvariant(),
            _ => text.ToUpperInvariant()
        };

        return new
        {
            original = text,
            converted = result,
            target_case = targetCase
        };
    }

    private async Task<object> ExecuteTextSplit(Dictionary<string, object> parameters)
    {
        await Task.CompletedTask;

        var text = parameters["text"].ToString() ?? string.Empty;
        var separator = parameters.GetValueOrDefault("separator", ",").ToString();
        var maxSplits = Convert.ToInt32(parameters.GetValueOrDefault("max_splits", -1));

        var parts = maxSplits > 0
            ? text.Split(separator, maxSplits, StringSplitOptions.None)
            : text.Split(separator, StringSplitOptions.None);

        return new
        {
            original = text,
            separator = separator,
            max_splits = maxSplits,
            parts = parts,
            count = parts.Length
        };
    }

    private async Task<object> ExecuteSystemInfo(Dictionary<string, object> parameters)
    {
        await Task.CompletedTask;

        var infoType = parameters.GetValueOrDefault("info_type", "all").ToString();
        var info = new Dictionary<string, object>();

        if (infoType == "all" || infoType == "os")
        {
            info["os"] = new
            {
                platform = Environment.OSVersion.Platform.ToString(),
                version = Environment.OSVersion.ToString(),
                machine_name = Environment.MachineName,
                processor_count = Environment.ProcessorCount
            };
        }

        if (infoType == "all" || infoType == "runtime")
        {
            info["runtime"] = new
            {
                version = Environment.Version.ToString(),
                working_directory = Environment.CurrentDirectory,
                system_directory = Environment.SystemDirectory,
                user_name = Environment.UserName
            };
        }

        if (infoType == "all" || infoType == "time")
        {
            info["time"] = new
            {
                utc_now = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
                local_now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                tick_count = Environment.TickCount64
            };
        }

        return info;
    }

    private bool ValidateParameterType(object? value, string expectedType)
    {
        if (value == null) return true;

        return expectedType.ToLower() switch
        {
            "string" => value is string,
            "number" => value is int or double or decimal or float,
            "boolean" => value is bool,
            "array" => value is Array || value is List<object>,
            "object" => value is Dictionary<string, object>,
            _ => true // 未知类型暂时通过
        };
    }
}